<?php
require "./function.php";
/**
 * @Author: Wherein
 * @Date: 2021-03-17 09:52
 * @Descripttion: 建造者模式
 */

// 抽象的建造者: 只定义方法
abstract class Builder
{

    abstract function buildA(); // 地基
    abstract function buildB(); // 钢筋工程
    abstract function buildC(); // 铺电线
    abstract function buildD(); // 粉刷

    // 完工: 得到产品
    abstract public function getProduct();
}


// 产品, 房子
class Product
{
    private $buildA;
    private $buildB;
    private $buildC;
    private $buildD;

    public function getBuildA()
    {
        return $this->buildA;
    }
    public function setBuildA($strBuild = '')
    {
        $this->buildA = $strBuild;
    }

    public function getBuildB()
    {
        return $this->buildB;
    }
    public function setBuildB($strBuild = '')
    {
        $this->buildB = $strBuild;
    }

    public function getBuildC()
    {
        return $this->buildC;
    }
    public function setBuildC($strBuild = '')
    {
        $this->buildC = $strBuild;
    }

    public function getBuildD()
    {
        return $this->buildD;
    }
    public function setBuildD($strBuild = '')
    {
        $this->buildD = $strBuild;
    }

    public function getProduct(){
        return null;
    }

    public function toString()
    {
        $arr = ['buildA' => $this->buildA, 'buildB' => $this->buildB, 'buildC' => $this->buildC, 'buildD' => $this->buildD];
        return json_encode($arr, JSON_UNESCAPED_UNICODE);
    }
}

// 具体的建造者: 工人
class Worker extends Builder
{
    private $product;

    public function __construct()
    {
        $this->product = new Product();
    }

    public function buildA()
    {
        $this->product->setBuildA('地基');
        dd('地基');
    }
    public function buildB()
    {
        $this->product->setBuildB('钢筋工程');
        dd('钢筋工程');
    }
    public function buildC()
    {
        $this->product->setBuildC('铺电线');
        dd('铺电线');
    }
    public function buildD()
    {
        $this->product->setBuildD('粉刷');
        dd('粉刷');
    }

    public function getProduct()
    {
        return $this->product;
    }
}


// 指挥: 核心  负责指挥构建一个工程, 工程如何构建, 由它决定
class Director
{
    // 指挥工人按照顺序建房子
    public function build($builder)
    {
        $builder->buildA();
        $builder->buildB();
        $builder->buildC();
        $builder->buildD();

        return $builder->getProduct();
    }
}


// 测试
$director = new Director();
// 指挥 具体的工人完成产品
$build = $director->build(new Worker());
$buildToString = $build->toString();
dd($build, $buildToString);
